/*
 * @Author: 火红色祥云 809880192@qq.com
 * @Date: 2023-11-26 12:24:03
 * @LastEditors: 火红色祥云 809880192@qq.com
 * @LastEditTime: 2023-11-26 12:25:17
 * @FilePath: /imx6ull-app/103_can/can.c
 * @Description: can应用程序测试
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <linux/can/raw.h>
#include <stdint.h>

#define CAN_INTERFACE "can0"

void error_exit(const char *message) {
    perror(message);
    exit(EXIT_FAILURE);
}

// 配置CAN套接字函数
void configure_can_socket(const char *interface, int *socket_fd) {
    struct sockaddr_can addr;  // CAN套接字地址结构体
    struct ifreq ifr;  // 网卡接口请求结构体

    *socket_fd = socket(PF_CAN, SOCK_RAW, CAN_RAW);  // 创建CAN套接字并返回套接字描述符
    if (*socket_fd == -1) {
        error_exit("Error opening socket");  // 打开套接字出错，退出程序
    }

    strcpy(ifr.ifr_name, interface);  // 复制接口名称到ifreq结构体
    ioctl(*socket_fd, SIOCGIFINDEX, &ifr);  // 获取接口索引

    addr.can_family = AF_CAN;  // 设置套接字地址族为AF_CAN
    addr.can_ifindex = ifr.ifr_ifindex;  // 设置套接字接口索引

    if (bind(*socket_fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
        error_exit("Error binding socket");  // 绑定套接字出错，退出程序
    }
}

// 发送CAN消息函数
void send_can_message(int socket_fd, uint32_t can_id, uint8_t *data, size_t data_len) {
    struct can_frame frame;  // 定义CAN帧结构体

    frame.can_id = can_id;  // 设置CAN ID
    frame.can_dlc = data_len;  // 设置数据长度
    memcpy(frame.data, data, data_len);  // 复制数据到帧数据部分

    if (write(socket_fd, &frame, sizeof(struct can_frame)) == -1) {  // 写入CAN消息
        error_exit("Error sending CAN message");  // 发送错误处理
    }
}

void receive_can_message(int socket_fd) {
    struct can_frame frame;
    ssize_t read_bytes;
// 接收CAN消息的函数
void receive_can_message(int socket_fd) {
    struct can_frame frame;  // CAN帧结构体
    ssize_t read_bytes;  // 读取的字节数

    read_bytes = read(socket_fd, &frame, sizeof(struct can_frame));  // 从套接字读取CAN消息到frame中
    if (read_bytes == -1) {
        error_exit("Error receiving CAN message");  // 读取失败，退出并打印错误信息
    }

    printf("Received CAN message - ID: 0x%lx, DLC: %d, Data:", frame.can_id, frame.can_dlc);  // 打印接收到的CAN消息的ID和DLC
    for (int i = 0; i < frame.can_dlc; ++i) {
        printf(" 0x%02x", frame.data[i]);  // 打印数据部分
    }
    printf("\n");
}
    read_bytes = read(socket_fd, &frame, sizeof(struct can_frame));
    if (read_bytes == -1) {
        error_exit("Error receiving CAN message");
    }

    printf("Received CAN message - ID: 0x%lx, DLC: %d, Data:", frame.can_id, frame.can_dlc);
    for (int i = 0; i < frame.can_dlc; ++i) {
        printf(" 0x%02x", frame.data[i]);
    }
    printf("\n");
}

int main() {
    int can_socket_fd;

    configure_can_socket(CAN_INTERFACE, &can_socket_fd);

    // 配置CAN套接字

    // 示例数据发送
    uint32_t can_id = 0x180150f1;
    uint8_t data[] = {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17};
    size_t data_len = sizeof(data) / sizeof(data[0]);

    send_can_message(can_socket_fd, can_id, data, data_len);
    // 发送CAN消息

    // 接收一个CAN消息
    receive_can_message(can_socket_fd);

    close(can_socket_fd);
    // 关闭CAN套接字

    return 0;
}
